#include "gd32w51x.h"
#include "stdio.h"
#include "string.h"
#include "UserTask.h"
#include "DevicesQueue.h"
#include "DevicesSoftTimer.h"
#include "DevicesKey.h"
#include "DevicesTSI.h"


KeyTypeDef g_typeKeyTouchData;
SoftTimerTaskTypeDef g_typeSoftTimerKeyTouchHanle = {0};




void vSoftTimerKeyTouchCallbackFunction(void *pvHandle)
{
    (void)pvHandle;

    /* 运行状态机，以检测是否有按键动作 */
    if(enumKeyStateMachine(&g_typeKeyTouchData) != keyNormal)
    {
        /* 把按键值push到FIFO */
        enumQueuePushDatas(&g_TypeQueueKeyInput, &g_typeKeyTouchData, sizeof(KeyTypeDef));

        /* 发送信号量 */
        rt_sem_release(g_SemKey);
    }
}

void vTSIInit(void)
{
    timer_ic_parameter_struct timer_icinitpara = {0};
    timer_parameter_struct timer_initpara = {0};

    rcu_periph_clock_enable(RCU_GPIOB);

    /*configure (TIMERx CHx) as alternate function*/
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1 | GPIO_PIN_2);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_166MHZ, GPIO_PIN_1 | GPIO_PIN_2);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_1 | GPIO_PIN_2);

    gpio_bit_reset(GPIOB, GPIO_PIN_1 | GPIO_PIN_2);

    rcu_periph_clock_enable(RCU_TIMER3);

    timer_deinit(TIMER3);

    /* TIMERx configuration */
    timer_initpara.prescaler         = 1 - 1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 65535;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER3, &timer_initpara);

    /* TIMERx CHx input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x0;
    timer_input_capture_config(TIMER3, TIMER_CH_1, &timer_icinitpara);
    timer_input_capture_config(TIMER3, TIMER_CH_2, &timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER3);
    /* clear channel x interrupt bit */
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_FLAG_CH1);
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_FLAG_CH2);
    /* channel x interrupt enable */
    timer_interrupt_enable(TIMER3, TIMER_INT_CH1);
    timer_interrupt_enable(TIMER3, TIMER_INT_CH2);

    nvic_irq_enable(TIMER3_IRQn, 3, 0);

    /* TIMER2 counter enable */
    timer_enable(TIMER3);


    g_typeKeyTouchData.uiKeyValueGet = uiKeyTouchValueGet;

    /* 软件定时器周期调用 */
    cSoftTimerCreateMs(&g_typeSoftTimerKeyTouchHanle, 20, softTimerOpen | softTimerCircular, vSoftTimerKeyTouchCallbackFunction);
}

/*
Return Value:   按键组合序号（头文件里有定义）
Parameters:     void
Description:    读取当前按键状态
*/
uint32_t uiKeyTouchValueGet(void)
{
    uint32_t Key = 0;
    uint16_t usTimerNow = 0, usTimerMin = 0xFFFF, usKeyTouch[KEY_TOUCH_CHANNEL_NUMBER] = {0}, i = 0;

    /* 输出低电平，以进行放电 */
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_1 | GPIO_PIN_2);


    for(i = 0; i < KEY_TOUCH_CHANNEL_NUMBER; ++i)
    {
        while(enumQueuePopDatas(&g_TypeQueueKeyTouch[i], &usTimerNow, sizeof(usTimerNow)) == queueNormal)
        {
            usKeyTouch[i] = (usKeyTouch[i] < usTimerNow) ? usTimerNow : usKeyTouch[i];
        }

        /* 找到所有触摸按键中充电时间最短的，作为空闲基准 */
        usTimerMin = usTimerMin > usKeyTouch[i] ? usKeyTouch[i] : usTimerMin;
    }

    /* 比空闲按键充电时间长2%（实验数据），则认定为此按键已按下 */
    if(usKeyTouch[0] > (usTimerMin * 1.02f))
        Key |= KEY_TOUCH1;
    if(usKeyTouch[1] > (usTimerMin * 1.02f))
        Key |= KEY_TOUCH2;


    TIMER_CNT(TIMER3) = 0;
    /* 配置为输入模式，以进行充电和等待上升沿触发 */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_1 | GPIO_PIN_2);


    return Key;
}
